home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Pascal / Snippets / ListDemo 1.0 / ListDemo.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-11-16  |  28.0 KB  |  631 lines  |  [TEXT/PJMM]

  1. program ListDemo;
  2. (* Demonstration of the List Manager, written June 24-25, 1988 by Richard Clark.       *)
  3. (* (eMail:: GEnie/MCI/DELPHI/MouseHole -- RDCLARK.  CompuServe users should use the    *)
  4. (*  MCI gateway.)                                                                      *)
  5. (* Written at the request of Kevin-Neil Klop of the Borland Product Support Roundtable *)
  6. (* on the GEnie network.                                                               *)
  7.  
  8. (* This software is in the Public Domain, and may be used and modified freely.         *)
  9.  
  10.  
  11. {*** Modernized by Ingemar R 1995: ***}
  12. {Added compilation switches for Think and Metrowerks (while keeping enough of}
  13. {the old stuff to make the few Turbo users - any left? - happy).Added window}
  14. {dragging.}
  15.  
  16. {Old compilation switches - beware for ones that have different meaning. /IR}
  17.  
  18. {$U- Don’t use standard I/O }
  19. {$D+ Generate MacsBug symbols }
  20. {$B+ Set the bundle bit, so we can have an icon }
  21. {$T APPL•PAS}
  22.                (* define the type and creator *)
  23. {$R ListDemo.rsrc}
  24.  
  25.  
  26. {Uses, not needed for Think /IR}
  27. {$IFC UNDEFINED THINK_PASCAL}
  28. {$IFC UNDEFINED MWERKS}
  29. {Old uses for Turbo Pascal}
  30.     uses
  31.         MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf;
  32. {$ELSEC}
  33. {MetroWerks, i.e. UPI}
  34.     uses
  35.         Types, QuickDraw, Menus, Windows, Events, Fonts, Lists, {}
  36.         TextEdit, Dialogs, Resources, ToolUtils, Devices;
  37. {$ENDC}
  38. {$ENDC}
  39.  
  40.  
  41. {$IFC UNDEFINED MWERKS}
  42.  
  43. {UPI names for some functions. I prefer keeping a big unit for these, so I can}
  44. {use the same in every project that supports both TP and MWP. /IR}
  45.  
  46. {AddResMenu}
  47.     procedure AppendResMenu (theMenu: MenuHandle; theType: ResType);
  48.     inline
  49.         $A94D;
  50.  
  51. {LDoDraw}
  52.     procedure LSetDrawingMode (drawIt: BOOLEAN; lHandle: ListHandle);
  53.     inline
  54.         $3F3C, $002C, $A9E7;
  55.  
  56. {GetItem}
  57.     procedure GetMenuItemText (theMenu: MenuHandle; item: INTEGER; var itemString: Str255);
  58.     inline
  59.         $A946;
  60.  
  61. {TextBox}
  62.     procedure TETextBox (text: univ Ptr; length: LONGINT; {CONST}
  63.                                     var box: Rect; just: INTEGER);
  64.     inline
  65.         $A9CE;
  66.  
  67. {$ENDC}
  68.  
  69.  
  70.  
  71.     const
  72.         mApple = 128;           (* Apple menu *)
  73.         iaAbout = 1;
  74.  
  75.         mFile = 129;           (* File menu *)
  76.         ifNew = 1;
  77.         ifClose = 2;
  78.   {----------------}
  79.         ifQuit = 4;
  80.  
  81.         wList = 128;           (* "List Window" has a resource id of 128 *)
  82.         dAbout = 128;           (* and so does our 'About" dialog *)
  83.  
  84.         sizes = 128;           (* The ID of a STR# containing our list of *)
  85.                                (* possible font sizes. *)
  86.  
  87.     var
  88.         quit: Boolean;
  89.         AppleMenu, FileMenu: MenuHandle;
  90.         MyWindow: WindowPtr;
  91.         FontList, SizeList: ListHandle;
  92.         FontRect, SizeRect, TextRect: Rect;
  93.         CurrFont, CurrSize: INTEGER;
  94.  
  95.  
  96.     procedure Initialize;
  97.     begin
  98.  (*------------------------------------------------------------------------------------------*)
  99.  (* Initialize the toolbox and most of our global variables.                                 *)
  100.  (*------------------------------------------------------------------------------------------*)
  101. {$IFC UNDEFINED MWERKS}
  102.         InitGraf(@thePort);
  103. {$ELSEC}
  104.         InitGraf(@qd.thePort);
  105. {$ENDC}
  106.         InitFonts;
  107.         InitWindows;
  108.         InitMenus;
  109.         TEInit;
  110.         InitDialogs(nil);
  111.  
  112.         CurrFont := 1;                         (* Use the default "Application" font *)
  113.         CurrSize := 12;                        (* 12 points is a good guess as to the size *)
  114.         myWindow := nil;
  115.         quit := FALSE;
  116.  
  117.  (*------------------------------------------------------------------------------------------*)
  118.  (* Add the Apple and File menus                                                             *)
  119.  (*------------------------------------------------------------------------------------------*)
  120.         AppleMenu := GetMenu(mApple);
  121.         AppendResMenu(AppleMenu, 'DRVR'); {AddResMenu}
  122.         InsertMenu(AppleMenu, 0);
  123.         FileMenu := GetMenu(mFile);
  124.         InsertMenu(FileMenu, 0);
  125.         DrawMenuBar;
  126.  
  127.         InitCursor;
  128.     end; (* Initialize *)
  129.  
  130.  
  131.     procedure SelectFont (fontName: Str255);
  132.         var
  133.             fontNum: INTEGER;
  134.             theCell: Cell;
  135.             found: Boolean;
  136.  
  137.     begin
  138.  (*------------------------------------------------------------------------------------------*)
  139.  (* Select the named font.                                                                   *)
  140.  (*                                                                                          *)
  141.  (*      This procedure sets our current font to the named font, marks the window for        *)
  142.  (* redrawing and hilights the selected font name in the font list.                          *)
  143.  (*                                                                                          *)
  144.  (*      We first locate the font name in the list using the LSearch() function.  If, for    *)
  145.  (* some strange reason, the name isn't found, then skip the rest of the procedure. Otherwise*)
  146.  (* we select the cell containing the font name.  Also, convert the font name into a font    *)
  147.  (* number and set our current font to that.                                                 *)
  148.  (*------------------------------------------------------------------------------------------*)
  149.         SetPt(theCell, 0, 0);                      (* set the starting point for our search *)
  150.         found := LSearch(POINTER(ORD(@fontname) + 1), length(fontName), nil, theCell, FontList);(* Locate the seletced name in the list *)
  151.         if found then
  152.             begin
  153.                 SetPort(MyWindow);                       (* Mark the text area of the window for redrawing *)
  154.                 InvalRect(TextRect);
  155.                 GetFNum(fontName, fontNum);              (* Convert the font name to a number… *)
  156.                 CurrFont := fontNum;                     (* …and remember the number *)
  157.                 if not (LGetSelect(FALSE, theCell, FontList)) then
  158.                     begin                                    (* If the cell is not presently selected, *)
  159.                         TextFace([]);                          (* then select it *)
  160.                         TextSize(12);                          (* NOTE: if we don't set the font/style/size first, *)
  161.                         TextFont(0);                           (* the list may not be re-drawn properly. *)
  162.                         LSetSelect(TRUE, theCell, FontList);
  163.                         if not (PtInRect(theCell, FontList^^.dataBounds)) then
  164.                             LAutoScroll(FontList);               (* If the selected cell isn't on screen, *)
  165.                                               (* THEN scroll it to the top of the list *)
  166.                     end;
  167.             end;
  168.     end; (* SelectFont *)
  169.  
  170.  
  171.     procedure SelectSize (sizeString: Str255);
  172.         var
  173.             sizeVal, count: INTEGER;
  174.             theCell: Cell;
  175.             found: Boolean;
  176.  
  177.     begin
  178.  (*------------------------------------------------------------------------------------------*)
  179.  (* Set the font size.                                                                       *)
  180.  (*                                                                                          *)
  181.  (*      This procedure is basically the same as the one above, except that it's working with*)
  182.  (* the font size information.                                                               *)
  183.  (*------------------------------------------------------------------------------------------*)
  184.         SetPt(theCell, 0, 0);                        (* set the starting point for our search *)
  185.         found := LSearch(POINTER(ORD(@sizeString) + 1), length(sizeString), nil, theCell, SizeList);(* Locate the selected size in the list *)
  186.         if found then
  187.             begin
  188.                 SetPort(MyWindow);
  189.                 InvalRect(TextRect);
  190.      (* Convert the string into an integer *)
  191.                 sizeVal := 0;
  192.                 for count := 1 to LENGTH(sizeString) do
  193.                     if (sizeString[count] >= '0') and (sizeString[count] <= '9') then
  194.                         sizeVal := 10 * sizeVal + (ORD(sizeString[count]) - ORD('0'));
  195.                 CurrSize := sizeVal;
  196.                 if not (LGetSelect(FALSE, theCell, SizeList)) then
  197.                     begin
  198.                         TextFace([]);
  199.                         TextSize(12);
  200.                         TextFont(0);
  201.                         LSetSelect(TRUE, theCell, SizeList);   (* so set the selection point *)
  202.                         if not (PtInRect(theCell, FontList^^.dataBounds)) then
  203.                             LAutoScroll(SizeList);               (* If the selected cell isn't on screen, *)
  204.                                               (* THEN scroll it to the top of the list *)
  205.                     end;
  206.             end;
  207.     end; (* SelectSize *)
  208.  
  209.  
  210.     procedure OpenMyWindow;
  211.         var
  212.             apFontName: Str255;
  213.  
  214.         procedure CreateLists;
  215.             const
  216.                 notDrawn = FALSE;                      (* symbolic constants used to make LNew() more readable *)
  217.                 noGrow = FALSE;
  218.                 noHScroll = FALSE;
  219.                 vScroll = TRUE;
  220.  
  221.             var
  222.                 dataBounds: Rect;
  223.                 cellSize: Point;
  224.                 numFonts, firstRow, count: INTEGER;
  225.                 fontRsrc: Handle;
  226.                 theID: INTEGER;
  227.                 theType: resType;
  228.                 name: Str255;
  229.                 theCell: Cell;
  230.  
  231.  
  232.         begin
  233.             SetRect(FontRect, 10, 10, 230, 140);      (* This rectangle will hold a list of fonts *)
  234.             SetRect(SizeRect, 240, 10, 310, 140);      (* This rectangle will hold a list of font sizes *)
  235.  
  236.             SetRect(dataBounds, 0, 0, 1, 0);           (* Specify an initial list that's 1 column wide by 0 rows deep *)
  237.             SetPt(cellSize, 0, 0);                     (* Let the list manager calculate the cell size *)
  238.  
  239.    (*------------------------------------------------------------------------------------------*)
  240.    (* Create an empty font list, 0 rows by 1 column                                            *)
  241.    (*------------------------------------------------------------------------------------------*)
  242.             FontRect.right := FontRect.right - 16;     (* The rectangle passed to LNew determines the size of the body *)
  243.                                               (* of the list; scroll bars are placed outside of the rectangle *)
  244.                                               (* Therefore, you should set your rectangle for the proper size *)
  245.                                               (* including the scroll bars, and adjust it before creating the *)
  246.                                               (* list.                                                        *)
  247.             FontList := LNew(FontRect, dataBounds, cellSize, 0, myWindow, notDrawn, noGrow, noHScroll, vScroll);     (* Create the list with the given physical boundaries, size,    *)
  248.     (* and options.  Note that it has to be attached to a window (a *)
  249.          (* dialog or alert will also work *)
  250.             FontList^^.selFlags := lDoHAutoscroll + lOnlyOne;    (* Set the options for this list (NOTE: we really don't have to *)
  251.            (* do this as these are the default settings, namely, allow     *)
  252.                                               (* automatic scrolling and only select one cell at a time.  But,*)
  253.                                               (* it never hurts to make certain that your options are set     *)
  254.                                               (* properly.                                                    *)
  255.             FontRect.right := FontRect.right + 16;
  256.  
  257.    (*------------------------------------------------------------------------------------------*)
  258.    (* Fill in the font list.                                                                   *)
  259.    (*                                                                                          *)
  260.    (*    We create the font list by counting the number of fonts in the system and adding that *)
  261.    (* many rows to our list.  Then, we get each font name and append it to the end of the list.*)
  262.    (*                                                                                          *)
  263.    (* A note on strings and the List Manager:                                                  *)
  264.    (*    All "pascal-format" strings contain a length byte as the first character.  The List   *)
  265.    (* Manager only wants the charaters contained in the string, without the length byte.  So,  *)
  266.    (* when we pass the information to the List manager, we need to pass a pointer to the second*)
  267.    (* character of the string.  The expression                                                 *)
  268.    (*                             POINTER(ORD(@string)+1)                                      *)
  269.    (* gets the address of the second character of the string.                                  *)
  270.    (*------------------------------------------------------------------------------------------*)
  271.             numFonts := CountResources('FOND');          (* get the number of fonts *)
  272.             firstRow := LAddRow(numFonts, 0, FontList);  (* Insert the proper number of rows *)
  273.             for count := 1 to numFonts do
  274.                 begin
  275.                     fontRsrc := GetIndResource('FOND', count); (* get each font *)
  276.                     GetResInfo(fontRsrc, theID, theType, name);(* and gets it's name (among other things) *)
  277.                     SetPt(theCell, 0, count - 1);              (* select the proper cell *)
  278.                     LSetCell(POINTER(ORD(@name) + 1), length(name), theCell, FontList);          (* and copy the information into it *)
  279.                 end;
  280.  
  281.    (*------------------------------------------------------------------------------------------*)
  282.    (* Create the Size list, o rows deep by 1 column wide                                       *)
  283.    (*------------------------------------------------------------------------------------------*)
  284.             SizeRect.right := SizeRect.right - 16;
  285.             SizeList := LNew(SizeRect, dataBounds, cellSize, 0, myWindow, notDrawn, noGrow, noHScroll, vScroll);
  286.             SizeRect.right := SizeRect.right + 16;
  287.  
  288.    (*------------------------------------------------------------------------------------------*)
  289.    (* Fill in the size list.                                                                   *)
  290.    (*                                                                                          *)
  291.    (*    We fill in the size list from a STR# resource (a list of strings).  Since Pascal      *)
  292.    (* makes it hard to get the number of strings in the list, we'll get each string one at a   *)
  293.    (* time and create the new rows as we go.  We're using strings instead of integers since    *)
  294.    (* the default list format is "string" and writing a custom list definition is outside the  *)
  295.    (* scope of this example.                                                                   *)
  296.    (*------------------------------------------------------------------------------------------*)
  297.             count := 1;
  298.             repeat
  299.                 GetIndString(name, sizes, count);        (* Get a size value from our list, or '' if we *)
  300.                 if (name <> '') then                     (* are at the end of the list of strings *)
  301.                     begin
  302.                         firstRow := LAddRow(1, -1, SizeList);  (* LAddRow will insert (the first number shown) rows starting *)
  303.                                               (* at row (the second number).  If the starting point is not  *)
  304.                                               (* within the list, LAddRow appends the requested number of   *)
  305.                                               (* rows.  Therefore, we are appending 1 row and getting beck  *)
  306.                                               (* the number of the new row.                                 *)
  307.                         SetPt(theCell, 0, firstRow);           (* get the cell we just installed… *)
  308.                         LSetCell(POINTER(ORD(@name) + 1), length(name), theCell, SizeList);      (* …and copy the information into it *)
  309.                         count := count + 1;
  310.                     end;
  311.             until (name = '');
  312.  
  313.             TextFace([]);                              (* Select the "System Font" (Chicago) before drawing the lists *)
  314.             TextSize(12);
  315.             TextFont(0);
  316.  
  317. {LDoDraw remaned to LSetDrawingMode /IR}
  318.             LSetDrawingMode(TRUE, FontList);                   (* we turned off drawing while building the lists *)
  319.             LSetDrawingMode(TRUE, SizeList);                   (* so we need to turn it on now                   *)
  320.         end; (* CreateLists *)
  321.  
  322.     begin
  323.  (*------------------------------------------------------------------------------------------*)
  324.  (* Create the window, if it doesn't exist already                                           *)
  325.  (*                                                                                          *)
  326.  (*     After we create the window, we'll attach the lists (yes, you have to create a window *)
  327.  (* before creating any lists) and slect our initial font and size (which includes setting   *)
  328.  (* the hilights in the 2 lists).                                                            *)
  329.  (*------------------------------------------------------------------------------------------*)
  330.         if (myWindow = nil) then
  331.             begin
  332.                 myWindow := GetNewWindow(wList, nil, WindowPtr(-1));
  333.                 DisableItem(FileMenu, ifNew);            (* Set the File menu entries so we can't open another window *)
  334.                 EnableItem(FileMenu, ifClose);
  335.                 CreateLists;
  336.                 GetFontName(1, apFontName);              (* get the name of the current application font *)
  337.                 SelectFont(apFontName);                  (* and use this font initially *)
  338.                 SelectSize('12');                        (* Use 12 point characters *)
  339.                 SetRect(TextRect, 10, 150, 310, 190);    (* This will hold the actual text display *)
  340.             end
  341.     end; (* OpenMyWindow *)
  342.  
  343.  
  344.     procedure CloseMyWindow;
  345.     begin
  346.  (*------------------------------------------------------------------------------------------*)
  347.  (* Remove the window                                                                        *)
  348.  (*                                                                                          *)
  349.  (*     Before we get rid of the window, we need to dispose of the lists (or risk a System   *)
  350.  (* Error message).  We'll also reset the File menu so we can open the window again.         *)
  351.  (*------------------------------------------------------------------------------------------*)
  352.         if (myWindow <> nil) then
  353.             begin
  354.                 LDispose(FontList);                     (* Get rid of the lists… *)
  355.                 LDispose(SizeList);
  356.                 DisposeWindow(myWindow);                (* and the window *)
  357.                 myWindow := nil;                        (* mark the window as disposed *)
  358.                 EnableItem(FileMenu, ifNew);            (* and set the file menu so the user can open *)
  359.                 DisableItem(FileMenu, ifClose);         (* a window *)
  360.             end;
  361.     end; (* CloseMyWindow *)
  362.  
  363.  
  364.     procedure DoMenus (menuCode: longint);
  365.         var
  366.             inMenu, inItem: integer;
  367.  
  368.    (* The following variables are used when opening a desk accessory *)
  369.             DAName: Str255;
  370.             oldPort: GrafPtr;
  371.             scratch: integer;
  372.  
  373.    (* Variables used with our "About" dialog *)
  374.             aboutDlg: DialogPtr;
  375.             itemHit: INTEGER;
  376.  
  377.     begin
  378.  (*------------------------------------------------------------------------------------------*)
  379.  (* Process a menu request                                                                   *)
  380.  (*                                                                                          *)
  381.  (*     We have to separate the menu code into its 2 parts, then take the appropriate        *)
  382.  (* actions.                                                                                 *)
  383.  (*------------------------------------------------------------------------------------------*)
  384.         if MenuCode <> 0 then
  385.             begin
  386.                 inMenu := HiWord(menuCode);
  387.                 inItem := LoWord(menuCode);
  388.                 case inMenu of
  389.                     mApple: 
  390.                         if (inItem = iaAbout) then
  391.                             begin
  392.                                 aboutDlg := GetNewDialog(dAbout, nil, WindowPtr(-1));
  393.                                 if (aboutDlg <> nil) then
  394.                                     ModalDialog(nil, itemHit);
  395.                                 DisposeDialog(aboutDlg);
  396.                             end
  397.                         else
  398.                             begin  (* We have a desk accessory *)
  399.                             (* Some DAs are ill-behaved and change the current GrafPort, so we'll save *)
  400.        (*and restore around them *)
  401.                                 GetPort(oldPort);
  402.                                 GetMenuItemText(AppleMenu, inItem, DAName);      (* (GetItem) Get the DA's name *)
  403.                                 scratch := OpenDeskAcc(DAName);          (* (OpenDeskAcc) Open it *)
  404.                                 SetPort(oldPort);                        (* and get our current window setting back *)
  405.                             end;  (* Apple menu selected *)
  406.  
  407.                     mFile: 
  408.                         case inItem of
  409.                             ifNew: 
  410.                                 OpenMyWindow;
  411.  
  412.                             ifClose: 
  413.                                 CloseMyWindow;
  414.  
  415.                             ifQuit: 
  416.                                 quit := TRUE;
  417.                         end; (* mFile: CASE inItem *)
  418.  
  419.                     otherwise
  420.                         SysBeep(5);
  421.                 end; (* CASE inMenu *)
  422.                 HiliteMenu(0);
  423.             end;
  424.     end; (* DoMenus *)
  425.  
  426.  
  427.     procedure DoUpdate (whichWindow: WindowPtr);
  428.         var
  429.             message: Str255;
  430.             scratch: Rect;
  431.  
  432.     begin
  433.  (*------------------------------------------------------------------------------------------*)
  434.  (* Update the window.                                                                       *)
  435.  (*                                                                                          *)
  436.  (*      The window contains three parts that we have to update -- the text area and the 2   *)
  437.  (* lists.                                                                                   *)
  438.  (*                                                                                          *)
  439.  (*      Notice the adjustments we make to the list rectangles before framing them.  If you  *)
  440.  (* don't do this, the framing rectangles might come out looking a little strange!           *)
  441.  (*------------------------------------------------------------------------------------------*)
  442.         BeginUpdate(whichWindow);
  443.         SetPort(whichWindow);
  444.         EraseRgn(whichWindow^.visRgn);                    (* Erase the area to be updated *)
  445.         TextFace([]);                                     (* Just plain text *)
  446.         TextSize(CurrSize);                               (* Our selected size *)
  447.         TextFont(CurrFont);                               (* our selected font *)
  448.         message := 'The quick brown fox jumped over the lazy dog.';
  449.         TETextBox(POINTER(ORD(@message) + 1), length(message), TextRect, teJustLeft); {TextBox}
  450.         InsetRect(TextRect, -2, -2);                        (* set up a 2-pixel margin around the text *)
  451.         FrameRect(TextRect);
  452.         InsetRect(TextRect, 2, 2);
  453.  
  454.         TextFont(0);                                      (* Reset to the current System font *)
  455.         TextSize(12);
  456.         LUpdate(whichWindow^.visRgn, FontList);           (* Draw the font list *)
  457.         LUpdate(whichWindow^.visRgn, SizeList);           (* Draw the size list *)
  458.         scratch := FontRect;                              (* Frame the font list *)
  459.         InsetRect(scratch, -1, -1);
  460.         scratch.right := scratch.right - 15;
  461.         FrameRect(scratch);
  462.  
  463.         scratch := SizeRect;                              (* Frame the size list *)
  464.         InsetRect(scratch, -1, -1);
  465.         scratch.right := scratch.right - 15;
  466.         FrameRect(scratch);
  467.  
  468.         EndUpdate(whichWindow);
  469.     end; (* DoUpdate *)
  470.  
  471.  
  472.     procedure DoMouseClick (theEvent: EventRecord; theWindow: WindowPtr);
  473.         var
  474.             localClick: Point;
  475.             isDoubleClick, isSelected: Boolean;
  476.             theCell: Cell;
  477.             nameLen, sizeLen: INTEGER;
  478.             fontName, sizeString: Str255;
  479.  
  480.     begin
  481.  (*------------------------------------------------------------------------------------------*)
  482.  (* Handle a MouseDown event in our window                                                   *)
  483.  (*                                                                                          *)
  484.  (*      We need to check if the click was in one of the lists and, if so, call LClick() for *)
  485.  (* the appropriate list.                                                                    *)
  486.  (*                                                                                          *)
  487.  (*      NOTE: LClick() expects the location to be in local coordinates.  If you forget to   *)
  488.  (* convert the mouse location to local coordinates, your lists won't select properly and    *)
  489.  (* you'll get all sorts of strange behaviors!                                               *)
  490.  (*------------------------------------------------------------------------------------------*)
  491.         localClick := theEvent.where;
  492.         SetPort(theWindow);
  493.         GlobalToLocal(localClick);
  494.         if PtInRect(localClick, FontRect) then
  495.             begin
  496.                 isDoubleClick := LClick(localClick, theEvent.modifiers, FontList);                 (* process the mouse click *)
  497.                 SetPt(theCell, 0, 0);
  498.                 isSelected := LGetSelect(TRUE, theCell, FontList);  (* Find the first (and only) selected *)
  499.                                                          (* cell at a location greater than or *)
  500.                                                          (* equal to  (0,0) *)
  501.                 nameLen := 255;                                     (* The maximum number of chars allowed in the string *)
  502.                 LGetCell(POINTER(ORD(@fontName) + 1), nameLen, theCell, FontList);        (* Get the text of the selected cell *)
  503.      {$R- Turn off range checking for the next operation, since Pascal doesn't like you to change the string length byte }
  504.                 fontName[0] := CHR(nameLen);                        (* Set the length byte of the string *)
  505.      {$R+ Range checking is back on}
  506.                 SelectFont(fontName);                               (* Use the selected font *)
  507.             end;
  508.  
  509.         if PtInRect(localClick, SizeRect) then
  510.             begin
  511.                 isDoubleClick := LClick(localClick, theEvent.modifiers, SizeList);                 (* process the mouse click *)
  512.                 SetPt(theCell, 0, 0);
  513.                 isSelected := LGetSelect(TRUE, theCell, SizeList);  (* Find the first (and only) selected *)
  514.                                                          (* cell at a location greater than or *)
  515.                                                          (* equal to  (0,0) *)
  516.                 sizeLen := 255;                                     (* The maximum number of chars allowed in the string *)
  517.                 LGetCell(POINTER(ORD(@sizeString) + 1), sizeLen, theCell, SizeList);      (* Get the text of the selected cell *)
  518.      {$R- Turn off range checking}
  519.                 sizeString[0] := CHR(sizeLen);                      (* Set the length byte of the string *)
  520.      {$R+ Range checking is back on}
  521.                 SelectSize(sizeString);                             (* Use the selected size *)
  522.             end;
  523.     end; (* DoMouseClick *)
  524.  
  525.  
  526.     procedure MainLoop;
  527.         var
  528.             theEvent: EventRecord;
  529.             location: integer;
  530.             whichWindow: WindowPtr;
  531.             menuCode: longint;
  532.             ch: char;
  533.             r: Rect;
  534.  
  535.     begin
  536.  (*------------------------------------------------------------------------------------------*)
  537.  (* Our main event loop.                                                                     *)
  538.  (*                                                                                          *)
  539.  (*      This is a pretty standard main event loop, except that I don't let you drag or      *)
  540.  (* resize the window.  Notice the special handling required for Activate events when you    *)
  541.  (* are working with lists.                                                                  *)
  542.  (*------------------------------------------------------------------------------------------*)
  543.         repeat
  544.             SystemTask;
  545.             if GetNextEvent(everyEvent, theEvent) then
  546.                 case (theEvent.what) of
  547.                     mouseDown: 
  548.                         begin
  549.                             location := FindWindow(theEvent.where, whichWindow);
  550.                             case location of
  551.                                 inMenuBar: 
  552.                                     begin
  553.                                         menuCode := MenuSelect(theEvent.where);
  554.                                         DoMenus(menuCode);
  555.                                     end; (* mouse in menu bar *)
  556.  
  557.                                 inContent: 
  558.                                     if FrontWindow <> whichWindow then
  559.                                         SelectWindow(whichWindow)                 (* Bring this window to the front *)
  560.                                     else
  561.                                         DoMouseClick(theEvent, whichWindow);      (* The user clicked in our window *)
  562.  
  563.                                 inGoAway: 
  564.                                     if TrackGoAway(whichWindow, theEvent.where) then
  565.                                         CloseMyWindow;
  566.  
  567.                                 inSysWindow: 
  568.                                     SystemClick(theEvent, whichWindow);
  569.  
  570.                                 inDrag: {Added by Ingemar R}
  571.                                     begin
  572.                                         if (whichWindow <> FrontWindow) and (BitAnd(theEvent.modifiers, cmdKey) = 0) then
  573.                                             SelectWindow(whichWindow);
  574.                     {Limit the dragging so that the window can't be dragged too far.}
  575. {$IFC UNDEFINED MWERKS}
  576.                                         r := screenBits.bounds;
  577. {$ELSEC}
  578.                                         r := qd.screenBits.bounds;
  579. {$ENDC}
  580.                                         InsetRect(r, 4, 4);
  581.                                         DragWindow(whichWindow, theEvent.where, r);
  582.                                     end;
  583.  
  584.                                 otherwise
  585.                                     ;
  586.                             end; (*  CASE location *)
  587.                         end; (* mouseDown *)
  588.  
  589.                     keyDown:                                     (* If it's a menu selection, then handle it *)
  590.                         if (BitAnd(theEvent.modifiers, CmdKey) <> 0) then
  591.                             begin
  592.                                 ch := chr(BitAnd(theEvent.message, CharCodeMask));
  593.                                 menuCode := MenuKey(ch);
  594.                                 DoMenus(menuCode);
  595.                             end; (* IF we have a command key *)
  596.  
  597.                     updateEvt: 
  598.                         DoUpdate(WindowPtr(theEvent.message));
  599.  
  600.                     activateEvt: 
  601.                         if (WindowPtr(theEvent.message) = MyWindow) then
  602.                             if ODD(theEvent.modifiers) then
  603.                                 begin (* Our window is coming to the front *)
  604.                                     LActivate(TRUE, FontList);           (* Enable the scroll bar, turn on the hilight, etc. *)
  605.                                     LActivate(TRUE, SizeList);
  606.                                 end
  607.                             else
  608.                                 begin (* Our window is going behind another one *)
  609.                                     LActivate(FALSE, FontList);          (* Deactivate the scroll bar, hide the hilight *)
  610.                                     LActivate(FALSE, SizeList);
  611.                                 end;
  612.  
  613.                     otherwise
  614.                         ;
  615.                 end; (* CASE theEvent.what *)
  616.         until quit;
  617.     end; (* MainLoop *)
  618.  
  619.  
  620.     procedure Cleanup;
  621.     begin
  622.         CloseMyWindow;
  623.     end; (* Cleanup *)
  624.  
  625.  
  626. begin
  627.     Initialize;
  628.     OpenMyWindow;
  629.     MainLoop;
  630.     Cleanup;
  631. end.